package com.alpha.eceasy.advice;

import com.alpha.eceasy.core.R;
import com.alpha.eceasy.exception.BizException;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.NestedRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 全局异常处理器
 *
 * @author huangpengfei
 */
@Slf4j
@RestController
@RestControllerAdvice
public class GlobalBizExceptionAdvice {

    /**
     * 全局业务异常.
     *
     * @param e the e
     * @return R 返回结果
     */
    @ExceptionHandler(BizException.class)
    @ResponseStatus(HttpStatus.OK)
    public R<String> handleGlobalException(BizException e) {
        log.error("全局业务异常信息 ex={},{}", e.getCode(), e.getMessage());

        return R.failed(null, e.getCode(), e.getMessage());
    }

    /**
     * 全局业务异常.
     *
     * @param e the e
     * @return R 返回结果
     */
    @ExceptionHandler(BadCredentialsException.class)
    @ResponseStatus(HttpStatus.OK)
    public R<String> handleGlobalException(BadCredentialsException e) {
        log.error("全局业务异常信息 ex={},{}", 50504, e.getMessage());

        return R.failed(null, 50504, e.getMessage());
    }

    /**
     * 全局业务异常.
     *
     * @param e the e
     * @return R 返回结果
     */
    @ExceptionHandler(NestedRuntimeException.class)
    @ResponseStatus(HttpStatus.OK)
    public R<String> handleGlobalException(NestedRuntimeException e) {
        log.error("全局Spring系统异常信息 ex={}", e.getMessage(), e);

        return R.failed(null, 400, e.getMessage());
    }

    /**
     * 全局异常.
     *
     * @param e the e
     * @return R 返回结果
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public R<Void> handleGlobalException(Exception e) {
        log.error("全局异常信息 ex={}", e.getMessage(), e);

        return R.failed(e.getLocalizedMessage());
    }

    /**
     * AccessDeniedException 拒绝访问异常
     *
     * @param e the e
     * @return R 返回结果
     */
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public R<Void> handleAccessDeniedException(AccessDeniedException e) {
        log.error("拒绝授权异常信息 ex={}", e.getMessage());
        return R.failed("权限不足，不允许访问");
    }

    /**
     * validation Exception 验证异常
     *
     * @param exception
     * @return R 返回结果
     */
    @ExceptionHandler({BindException.class})
    @ResponseStatus(HttpStatus.OK)
    public R<Void> handleBodyValidException(BindException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        // 插入log 的逻辑
        return R.failed(fieldErrors.get(0).getDefaultMessage());
    }

    /**
     * 避免 404 重定向到 /error 导致NPE ,ignore-url 需要配置对应端点
     *
     * @return R 返回结果
     */
    @Hidden
    @DeleteMapping("/error")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public R<Void> noHandlerFoundException() {
        return R.failed(HttpStatus.NOT_FOUND.getReasonPhrase());
    }


}